package client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.Element;

/**
 * @author Ayzen
 * @version 1.0 29.04.2007 23:44:10
 */
public class Test implements EntryPoint {

  
  public static final String TAG =
          "<applet name='AppletConnection' ARCHIVE = 'javatext.jar' CODEBASE = '.' width='1' height='1' " +
          "style='position: absolute; left: -500px; top: -500px'" +
          "code='TextApplet.class' mayscript><param name='id' value='{0}'></applet>";

  private int id = 0;

  private HTML javaTag;
  private JavaScriptObject applet;

  private boolean connected = false;

  private ScrollPanel scrollPanel;
  private VerticalPanel history = new VerticalPanel();
  private TextBox input = new TextBox();
  TextBox tbHost = new TextBox();

  public void onModuleLoad() {
    initGUI();
    initApplet();
  }

  private void initApplet() {
    Panel root = RootPanel.get();

    root.remove(javaTag);

    initFunctions(id);

    javaTag = new HTML();
    javaTag.setSize("0", "0");
    javaTag.setHTML(TAG.replaceAll("[{][0][}]", String.valueOf(id)));

    root.add(javaTag);
  }

  private void initGUI() {
    VerticalPanel mainPanel = new VerticalPanel();
    mainPanel.setBorderWidth(1);
    scrollPanel = new ScrollPanel(history);
    scrollPanel.setSize("600", "300");
    input.setWidth("600");

    HorizontalPanel controlPanel = new HorizontalPanel();
    Button btnSend = new Button("Send");
    Button btnConnect = new Button("Connect");
    Button btnDisconnect = new Button("Disconnect");
    controlPanel.add(btnSend);
    controlPanel.add(btnConnect);
    controlPanel.add(btnDisconnect);
    controlPanel.add(tbHost);

    tbHost.setText("127.0.0.1:777");

    input.addKeyboardListener(new KeyboardListenerAdapter(){
      public void onKeyPress(Widget sender, char keyCode, int modifiers) {
        if (keyCode == KeyboardListener.KEY_ENTER)
          sendMessage();
      }
    });

    btnSend.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        sendMessage();
      }
    });

    btnConnect.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        println(" ** Connecting to server...");
        String[] hostPort = tbHost.getText().split("[:]");
        connectImpl(hostPort[0], Integer.parseInt(hostPort[1]));
      }
    });

    btnDisconnect.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        if (connected) {
          connected = false;
          println(" ** Disconnected from server.");
          disconnectImpl();
        }
        else
          println(" ** Not connected to server.");
      }
    });

    mainPanel.add(scrollPanel);
    mainPanel.add(input);
    mainPanel.add(controlPanel);

    RootPanel.get().add(mainPanel);

    println("Welcome to Sockets test application :)");
  }

  private void sendMessage() {
    if (connected) {
      String data = input.getText();
      input.setText("");
      sendImpl(data);
      println(" >> " + data);
    }
    else {
      println(" ** " + "Not connected to server.");
    }
  }

  private void println(String message) {
    history.add(new Label(message));
    scrollToBottom();
  }

  public void scrollToBottom() {
    scrollToBottomImpl(scrollPanel.getElement());
  }

  private native void scrollToBottomImpl(Element element) /*-{
    element.scrollTop = element.scrollHeight;
  }-*/;

  private void onConnect() {
    connected = true;
    println(" ** Connected to server.");
  }

  private void onData(int data) {
    if (connected) {
      println(" << Received bytes: " + data);
      println(" << " + readImpl());
    }
  }

  private void onSecurityError(String mesage) {
    println(" ** Security error: " + mesage);
  }

  private void onIOError(String message) {
    println(" ** IO error: " + message);
  }

  private void onClose() {
    println(" ** Server closed connection.");
    connected = false;
  }

  // Functions for Applet support

  private native void initFunctions(int id)/*-{
    var instance = this;

    $wnd["java_" + id + "_onReady"] = function(applet) {
      instance.@client.Test::applet = applet;
    }
    $wnd["java_" + id + "_onConnect"] = function(success) {
      instance.@client.Test::onConnect()();
    }
    $wnd["java_" + id + "_onClose"] = function() {
      instance.@client.Test::onClose()();
    }
    $wnd["java_" + id + "_onData"] = function(data) {
      instance.@client.Test::onData(I)(data);
    }
    $wnd["java_" + id + "_onSecurityError"] = function(msg) {
      instance.@client.Test::onSecurityError(Ljava/lang/String;)(msg);
    }
    $wnd["java_" + id + "_onIOError"] = function(msg) {
      instance.@client.Test::onIOError(Ljava/lang/String;)(msg);
    }
  }-*/;

  private native void connectImpl(String host, int port)/*-{
    this.@client.Test::applet.connect(host, port);
  }-*/;

  private native void disconnectImpl()/*-{
    this.@client.Test::applet.close();
  }-*/;

  private native void sendImpl(String data)/*-{
    this.@client.Test::applet.write(data);
  }-*/;

  private native String readImpl()/*-{
    return this.@client.Test::applet.read();
  }-*/;

}
